package net.xinqushi.collection.concurrent;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.PriorityBlockingQueue;
import java.util.concurrent.atomic.AtomicLong;

/**
 * @author xjie 2019/7/29 10:59
 * @description  优先级队列， 堆排序
 */
public class PriorityBlockingQueueTest {

    public static void main(String[] args) {
        //Comparable 顺序排序
        FIFOEntry<Integer> fifoEntry = new FIFOEntry<>(1);
        FIFOEntry<Integer> fifoEntry2 = new FIFOEntry<>(3);
        FIFOEntry<Integer> fifoEntry3 = new FIFOEntry<>(2);
        PriorityBlockingQueue<FIFOEntry<Integer>> queue = new PriorityBlockingQueue<FIFOEntry<Integer>>();
        queue.add(fifoEntry);
        queue.add(fifoEntry2);
        queue.add(fifoEntry3);
        while (null != queue.peek()){
            System.out.println(queue.poll().getEntry());
        }
        //Comparable 顺序排序
        PriorityBlockingQueue<Integer> queue2 = new PriorityBlockingQueue<Integer>();
        queue2.add(1);queue2.add(5);queue2.add(2);queue2.add(3);
        while (null != queue2.peek()){
            System.out.println(queue2.poll());
        }
        //插入 顺序排序
        BlockingQueue<Integer> blockingQueue = new LinkedBlockingQueue<>();
        blockingQueue.add(1);blockingQueue.add(3);blockingQueue.add(5);blockingQueue.add(2);
        while (null != blockingQueue.peek()){
            System.out.println(blockingQueue.poll());
        }
    }

    //FIFO 优先级队列
    //java API PriorityBlockingQueue Comparable demo
    static class FIFOEntry<E extends Comparable<? super E>>
            implements Comparable<FIFOEntry<E>> {
        static final AtomicLong seq = new AtomicLong(0);
        final long seqNum;
        final E entry;

        public FIFOEntry(E entry) {
            seqNum = seq.getAndIncrement();
            this.entry = entry;
        }

        public E getEntry() {
            return entry;
        }

        public int compareTo(FIFOEntry<E> other) {
            int res = entry.compareTo(other.entry);
            if (res == 0 && other.entry != this.entry)
                res = (seqNum < other.seqNum ? -1 : 1);
            return res;
        }
    }


}
